use std::any::{Any, TypeId};
use rpc::codec::RpcEncode;
use rpc::RpcResult;

macro_rules! check_result {
    // 如果表达式是 Ok(...)，则直接使用
    (Ok($e:expr)) => { Ok(Box::new($e.unwrap())) };
    // 如果表达式是 Err(...)，则直接使用
    (Err($e:expr)) => { Err($e.err().unwrap()) };
    // 对于其他表达式，我们假设它不是Result，将其包装在Ok中
    ($e:expr) => { Ok(Box::new($e)) };
}

macro_rules! expr_type {
    ($expr:expr) => {{
        // 使用 std::mem::discriminant 进行更精确的判断
        use std::mem::discriminant;

        let value = $expr;
        let disc = discriminant(&value);

        if disc == discriminant(&Ok::<i32, i32>(0)) || disc == discriminant(&Err::<i32, i32>(0)) {
            "Result".to_string()
        } else if disc == discriminant(&Some::<i32>(0)) || disc == discriminant(&None::<i32>) {
            "Option".to_string()
        } else {
            "Other".to_string()
        }
    }};
}

#[test]
fn main() {
    let result: Result<i32, &str> = Ok(42);
    let option: Option<i32> = Some(42);

    // println!("{}", expr_type!(result));  // 输出: Result
    // println!("{}", expr_type!(option));  // 输出: Option
}

macro_rules! try_unwrap {
    // 处理 Result
    ($expr:expr) => {
        match $expr {
            Ok(val) => val,
            Err(e) => {
                eprintln!("Error: {:?}", e);
                return Err(e.into());
            }
        }
    };
    // 处理 Option
    ($expr:expr, $default:expr) => {
        match $expr {
            Some(val) => val,
            None => $default,
        }
    };
}

macro_rules! type_name {
    ($expr:expr) => {{
        // 获取类型的字符串表示
        std::any::type_name_of_val(&$expr)
    }};
}

#[test]
fn example() -> Result<(), Box<dyn std::error::Error>> {
    let result: Result<i32, &str> = Ok(42);
    let value = type_name!(result);  // 解包 Result

    let option: Option<i32> = Some(100);
    let opt_value = type_name!(option);  // 解包 Option，提供默认值

    println!("Result value: {}", value);
    println!("Option value: {}", opt_value);

    println!("dddd: {}", type_name!(32));

    Ok(())
}

#[test]
fn test() {
    let t = 32i32;
}

#[macro_export]
macro_rules! t_result {
    ($e:expr) => {
        if std::any::type_name_of_val(&$e).contains("Result") {
            return match $e {
                Ok(v) => Ok(Box::new(v)),
                Err(e) => Err(Box::new(e.into())),
            };
        } else {
            return Ok(Box::new($e));
        }
    };
}

#[test]
fn test_is_result()->RpcResult<()> {
    let t: RpcResult<i32> = Ok(23);
    // let t11 : RpcResult<Box<dyn RpcEncode>> = t_result!(t);
    //
    // let t1 = 32i32;
    // let t12 : RpcResult<Box<dyn RpcEncode>> = t_result!(t1);
    Ok(())
}